package com.lovo.manage_back.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lovo.manage_back.auth.RestAuthorizationFilter;
import com.lovo.manage_back.bean.Authority;
import com.lovo.manage_back.dao.AuthorityMapper;
import com.lovo.manage_back.result.GlobalHandleException;
import com.lovo.manage_back.result.ResultCode;
import com.lovo.manage_back.service.AuthorityService;
import jakarta.servlet.Filter;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
public class AuthorityServiceImpl extends ServiceImpl<AuthorityMapper, Authority> implements AuthorityService {
    @Autowired
    @Lazy
    private ShiroFilterFactoryBean shiroFilterFactoryBean;
    @Override
    public Map<String, String> loadFilterChainDefinitionMap() {
        //配置拦截链 使用LinkedHashMap,因为LinkedHashMap是有序的，shiro会根据添加的顺序进行拦截
        // Map<K,V> K指的是拦截的url V值的是该url是否拦截
        Map<String,String> filterChainMap = new LinkedHashMap<String,String>(16);
        //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问,先配置anon再配置authc。
        filterChainMap.put("/users/login","anon");
        List<Authority> authorityList = this.list();
        for (Authority authority:authorityList) {
            String url = authority.getPath();
            if(authority.getMethod() != null && !"".equals(authority.getMethod())){
                url += "==" + authority.getMethod();
            }
            filterChainMap.put(url,"perms["+authority.getName()+"]");
        }
        filterChainMap.put("/swagger-ui/**","anon");
        filterChainMap.put("/v3/api-docs/**","anon");
        filterChainMap.put("/**", "authc");
        System.out.println("刷新权限：" + filterChainMap);
        return filterChainMap;
    }

    @Override
    public void updatePermission() throws Exception {
        synchronized (this) {
            AbstractShiroFilter shiroFilter;
            try {
                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
            } catch (Exception e) {
                throw new Exception("get ShiroFilter from shiroFilterFactoryBean error!");
            }
            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

            // 清空拦截管理器中的存储
            manager.getFilterChains().clear();
            // 清空拦截工厂中的存储,如果不清空这里,还会把之前的带进去
            //            ps:如果仅仅是更新的话,可以根据这里的 map 遍历数据修改,重新整理好权限再一起添加
            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
            // 动态查询数据库中所有权限
            shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitionMap());
            // 重新构建生成拦截
            Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
            for (Map.Entry<String, String> entry : chains.entrySet()) {
                manager.createChain(entry.getKey(), entry.getValue());
            }

        }
    }

    @Override
    @Transactional
    public int add(Authority authority) throws GlobalHandleException {
        try {
            this.save(authority);
            updatePermission();
        } catch (Exception e) {
            throw new GlobalHandleException(ResultCode.SERVER_INNER_ERROR);
        }
        return 1;
    }
}
